package com.turing.post.organization.impl;

import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;

import com.turing.post.common.util.PCPSCommonDao;
import com.turing.post.common.util.SysOperLog;
import com.turing.post.common.util.SysOperLogDao;
import com.turing.post.organization.util.Merchant;
import com.turing.post.organization.util.MerchantContract;
import com.turing.post.organization.util.MerchantContractDao;
import com.turing.post.organization.util.MerchantDao;
import com.turing.post.organization.util.MerchantFeeSettlementPolicy;
import com.turing.post.organization.util.MerchantFeeSettlementPolicyBusiness;
import com.turing.post.organization.util.MerchantFeeSettlementPolicyDao;
import com.turing.post.organization.util.OrganApplicationException;
import com.turing.post.organization.util.OrganRespCode;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;
import com.turing.post.util.PCPSWebInput;

/**
 * 商户手续费收入结算策略业务实现
 * 
 * @author zxp
 * @Jan 3, 2013
 */
@Stateless(mappedName = "organization.impl.MerchantFeeSettlementPolicyBusinessImpl")
@Remote
@Local
public class MerchantFeeSettlementPolicyBusinessImpl implements
		MerchantFeeSettlementPolicyBusiness {

	@EJB(mappedName = "organization.impl.MerchantFeeSettlementPolicyDaoImpl")
	private MerchantFeeSettlementPolicyDao merchantFeeSettlementPolicyDaoImpl;

	@EJB(mappedName = "common.impl.PCPSCommonDaoImpl")
	private PCPSCommonDao commonDaoImpl;

	@EJB(mappedName = "common.impl.SysOperLogDaoImpl")
	private SysOperLogDao sysOperLogDaoImpl;

	@EJB(mappedName = "organization.impl.MerchantContractDaoImpl")
	private MerchantContractDao mctDao;

	@EJB(mappedName = "organization.impl.MerchantDaoImpl")
	private MerchantDao mrchDao;

	private void errException(String error) throws PCPSApplicationException {
		throw new OrganApplicationException(
				OrganApplicationException.ERRCODE_CATEGORY_APPLICATION,
				OrganRespCode.MERCHANTFEEPOLICY_INSERT_UPDATE, error);
	}

	@Override
	public void insertMerchantFeeSettlementPolicyInfo(PCPSWebInput webInput,
			MerchantFeeSettlementPolicy mfsp) throws PCPSApplicationException {
		if (PCPSUtil.isEmpty(mfsp.getMerchantNo())) {
			errException("商户号为空!");
		}
		if (mfsp.getContractId() == null) {
			errException("合同编号为空!");
		}
		MerchantContract mct = mctDao.getMerchantContractById(mfsp
				.getContractId());
		if (mct == null) {
			errException("策略对应合同未找到!");
		}
		// 策略类型取合同策略类型
		mfsp.setPolicy(mct.getPolicy());
		// 策略时间取合同时间
		mfsp.setPolicyStartDate(mct.getStartDate());
		mfsp.setPolicyEndDate(mct.getEndDate());

		if (PCPSUtil.isEmpty(mfsp.getFeePolicyName())) {
			errException("策略描述为空!");
		}
		if (mfsp.getFeeRatio() == null) {
			errException("费率为空!");
		}
		if (mfsp.getLimitAmount() == null) {
			errException("累计消费阀值为空!");
		}
		// 检查策略合法性
		Merchant merchant = mrchDao.getMerchantByMerchantNo(mfsp
				.getMerchantNo());
		checkMrchNoAndDateIncludeOrOverlapping(merchant.getMerchantName(), mfsp);

		mfsp.setOperId(webInput.getOperId());
		mfsp.setStatus(MerchantFeeSettlementPolicy.STATUS_DRAFT);// 状态草稿
		mfsp.setFloatFeeRatio(BigInteger.ZERO);// FloatFeeRatio 浮动比率(已删除)
		// 主键
		mfsp.setFeePolicyId(commonDaoImpl.getUniqueIntegerKey());
		// 上次修改时间
		mfsp.setLastModifyTime(commonDaoImpl.getDatabaseSysTime());
		merchantFeeSettlementPolicyDaoImpl
				.insertMerchantFeeSettlementPolicy(mfsp);// 插入日志数据
		insertRecordingOperationLog(webInput, "创建商户手续费结算策略", mfsp,
				SysOperLog.operType_Add, "FeePolicyName:"
						+ mfsp.getFeePolicyName());
	}

	// 修改策略必须审核
	@Override
	public void updateMerchantFeeSettlementPolicyInfo(PCPSWebInput webInput,
			MerchantFeeSettlementPolicy mfsp) throws PCPSApplicationException {
		MerchantFeeSettlementPolicy _mfsp = merchantFeeSettlementPolicyDaoImpl
				.getMerchantFeeSettlementPolicyByFeePolicyId(mfsp
						.getFeePolicyId());
		if (_mfsp == null) {
			errException("商户手续费收入结算策略系统中不存在!");
		}

		if (PCPSUtil.isEmpty(mfsp.getMerchantNo())) {
			errException("商户号为空!");
		}
		_mfsp.setMerchantNo(mfsp.getMerchantNo());

		if (mfsp.getContractId() == null) {
			errException("合同编号为空!");
		}
		_mfsp.setContractId(mfsp.getContractId());

		if (PCPSUtil.isEmpty(mfsp.getFeePolicyName())) {
			errException("策略描述为空!");
		}
		_mfsp.setFeePolicyName(mfsp.getFeePolicyName());

		if (PCPSUtil.isEmpty(mfsp.getPolicy())) {
			errException("基本策略为空!");
		}
		_mfsp.setPolicy(mfsp.getPolicy());
		_mfsp.setBusinessType(mfsp.getBusinessType());

		if (mfsp.getFeeRatio() == null) {
			errException("费率为空!");
		}
		_mfsp.setFeeRatio(mfsp.getFeeRatio());

		// if (mfsp.getFloatFeeRatio() == null) {
		// errException("浮动比率为空!");
		// }
		// _mfsp.setFloatFeeRatio(mfsp.getFloatFeeRatio());
		if (mfsp.getFloatFeeRatio() == null) {
			mfsp.setFloatFeeRatio(BigInteger.ZERO);
		}

		if (mfsp.getLimitAmount() == null) {
			errException("累计消费阀值为空!");
		}
		_mfsp.setLimitAmount(mfsp.getLimitAmount());

		if (mfsp.getPolicyStartDate() == null) {
			errException("执行起始日为空!");
		}
		_mfsp.setPolicyStartDate(mfsp.getPolicyStartDate());

		if (mfsp.getPolicyEndDate() == null) {
			errException("执行终止日为空!");
		}
		_mfsp.setPolicyEndDate(mfsp.getPolicyEndDate());

		_mfsp.setRemark(mfsp.getRemark());
		// 上次修改时间
		_mfsp.setLastModifyTime(commonDaoImpl.getDatabaseSysTime());
		_mfsp.setStatus(MerchantFeeSettlementPolicy.STATUS_DRAFT);// 状态草稿
		merchantFeeSettlementPolicyDaoImpl
				.updateMerchantFeeSettlementPolicy(_mfsp);
		// 插入日志数据
		insertRecordingOperationLog(webInput, "修改商户手续费结算策略", _mfsp,
				SysOperLog.operType_Edit, "FeePolicyName:"
						+ mfsp.getFeePolicyName());
	}

	// 审核
	@Override
	public void auditMerchantFeeSettlementPolicyInfo(PCPSWebInput webInput,
			MerchantFeeSettlementPolicy mfsp) throws PCPSApplicationException {
		MerchantFeeSettlementPolicy _mfsp = merchantFeeSettlementPolicyDaoImpl
				.getMerchantFeeSettlementPolicyByFeePolicyId(mfsp
						.getFeePolicyId());
		if (_mfsp == null) {
			errException("商户手续费收入结算策略系统中不存在!");
		}
		if (_mfsp.getOperId().intValue() == webInput.getOperId().intValue()) {
			errException("审核人不能为创建人!");
		}
		_mfsp.setAuthTime(commonDaoImpl.getDatabaseSysTime());
		_mfsp.setAuthOperId(webInput.getOperId());
		_mfsp.setAuthRemark(mfsp.getAuthRemark());
		_mfsp.setStatus(mfsp.getStatus());
		merchantFeeSettlementPolicyDaoImpl
				.updateMerchantFeeSettlementPolicy(_mfsp);
		// 插入日志数据
		insertRecordingOperationLog(webInput, "审核商户手续费结算策略", _mfsp,
				SysOperLog.operType_Edit, "FeePolicyName:"
						+ mfsp.getFeePolicyName());
	}

	/**
	 * 根据商户号，日期校验结算策略，如通过返回ok，否侧返回错误信息
	 * 
	 * @param merchantno
	 * @param trandate
	 * @return
	 */
	@Override
	public String checkMerchantFeeSettlementPolicyByMerchantNoAndTrandate(
			String merchantno, Date trandate) {
		List<MerchantFeeSettlementPolicy> plist = merchantFeeSettlementPolicyDaoImpl
				.getMerchantFeeSettlementPolicyListByMerchantnoAndTrandate(
						merchantno, trandate);
		HashMap<String, String> businesshm = new HashMap<String, String>();
		MerchantFeeSettlementPolicy ms = null;
		String policy = null;
		long LimitAmount = 0;
		Date startdate = null;
		Date enddate = null;
		boolean isZero = false;
		for (int i = 0; i < plist.size(); i++) {
			ms = plist.get(i);
			// 如果含有0值，置isZero为true
			if (ms.getLimitAmount().equals(BigInteger.ZERO))
				isZero = true;

			// 如果结果集不止一条记录，policy必须相同，不相同校验不通过
			if (i == 0) {
				policy = ms.getPolicy();
				LimitAmount = ms.getLimitAmount().longValue();
				startdate = ms.getPolicyStartDate();
				enddate = ms.getPolicyEndDate();
			} else {
				// 比较时间段，如不同说明设置错误
				if (startdate.compareTo(ms.getPolicyStartDate()) != 0
						|| enddate.compareTo(ms.getPolicyEndDate()) != 0)
					return "结算策略设置有误，该日期所属多个时间段不统一的结算策略。";
				startdate = ms.getPolicyStartDate();
				enddate = ms.getPolicyEndDate();
				// 用结算策略种类与前一个对比，如不同说明出现多种结算策略，返回错误提示
				if (!policy.equals(ms.getPolicy()))
					return "结算策略设置有误，该时间段内存在多种结算方式。";
				policy = ms.getPolicy();
				// 用消费阀值与上一个对比，因为是order by取出的，因此如果小于等于上一个值，表明阀值重叠返回错误信息
				if (ms.getPolicy().equals(
						MerchantFeeSettlementPolicy.POLICY_LADDERRETROSPECTIVE)
						|| ms
								.getPolicy()
								.equals(
										MerchantFeeSettlementPolicy.POLICY_NORETROSPECTIVE)) {
					if (ms.getLimitAmount().longValue() <= LimitAmount)
						return "结算策略设置有误，该时间段消费阀值存在重复。";
				}

				LimitAmount = ms.getLimitAmount().longValue();
			}

			// 如果基本策略是固定费率，则该时间段内必须只有一条记录。
			if (ms.getPolicy().equals(
					MerchantFeeSettlementPolicy.POLICY_FIXEDRATE)
					&& plist.size() > 1)
				return "同一时间段存在多种固定费率，应只存在一种，请检查。";
			// 如果是按业务类型结算，则改时间段内每种business只可以有一条结算策略。
			if (ms.getPolicy().equals(
					MerchantFeeSettlementPolicy.POLICY_BYBUSINESSTYPE)) {
				if (businesshm.containsKey(ms.getBusinessType()))
					return "同一种业务类型存在多种结算比率。业务类型：" + ms.getBusinessType();
				businesshm.put(ms.getBusinessType(), ms.getBusinessType());
			}
			// 如果是阶梯类型，策略中必须含有为阀值为0的策略
			if (ms.getPolicy().equals(
					MerchantFeeSettlementPolicy.POLICY_LADDERRETROSPECTIVE)
					|| ms.getPolicy().equals(
							MerchantFeeSettlementPolicy.POLICY_NORETROSPECTIVE)) {
				if (!isZero)
					return "在阶梯类策略中必须含有为阀值为0的策略";
			}
		}
		return "ok";
	}

	/**
	 * 根据商户号，日期,交易阀值 返回唯一结算策略,如果结算策略有误，返回-99999
	 * 
	 * @param merchantno
	 * @param trandate
	 * @return
	 */
	@Override
	public Integer getCheckedMerchantFeeSettlementPolicyByMerchantNoAndTrandate(
			String merchantno, Date trandate) {
		// 得到已达到阀值，生效的策略集合
		List<MerchantFeeSettlementPolicy> plist = merchantFeeSettlementPolicyDaoImpl
				.getEffectMerchantFeeSettlementPolicyList(merchantno, trandate);
		MerchantFeeSettlementPolicy ms = null;
		Integer feeratio = -99999;// 如果无法得到正确的费率就返回-99999
		for (int i = 0; i < plist.size(); i++) {
			ms = plist.get(i);
			if (i == 0) {
				// 第一个循环，给feeratio
				feeratio = ms.getFeeRatio().intValue();
			} else {
				// 不止一条记录时，比较，最终返回最大的feeratio
				if (ms.getFeeRatio().intValue() > feeratio)
					feeratio = ms.getFeeRatio().intValue();
			}
		}
		return feeratio;
	}

	private void insertRecordingOperationLog(PCPSWebInput webInput,
			String logName, MerchantFeeSettlementPolicy obj, String operType,
			String lastFieldName) throws PCPSApplicationException {
		String logRemark = PCPSUtil.RecordingOperationLog(obj, lastFieldName);
		if (!PCPSUtil.isEmpty(logRemark)) {
			// 插入数据库日志
			SysOperLog sysOperLog = new SysOperLog();
			if (webInput != null && webInput.getOperId() != null) {
				sysOperLog.setOperId(webInput.getOperId());
				sysOperLog.setOperType(operType);
				sysOperLog.setLogName(logName);
				if (webInput != null) {
					sysOperLog.setIpAddress(webInput.getIpAddress());
				}
				if (!PCPSUtil.isEmpty(webInput.getOperBranchNo())) {
					sysOperLog.setIssueCompanyNo(webInput.getOperBranchNo()
							.substring(0, 6));
					sysOperLog.setBranchNo(webInput.getOperBranchNo());
				}
				sysOperLog.setRemark(logRemark);
				sysOperLogDaoImpl.insertSysOperLog(sysOperLog);
			}
		}
	}

	/**
	 * 增加,修改,审核时检查策略
	 * 
	 * @param mrchName
	 * @param mfsp
	 * @throws PCPSApplicationException
	 */
	private void checkMrchNoAndDateIncludeOrOverlapping(String mrchName,
			MerchantFeeSettlementPolicy mfsp) throws PCPSApplicationException {
		// 包含和交叉
		List<MerchantFeeSettlementPolicy> mfspsInclude = null;
		// 重复和重叠
		List<MerchantFeeSettlementPolicy> mfspsOverlapping = null;
		/**
		 * 0-固定比率(基本策略): 同一商户同一时间段内有且只有一条策略,而且时间不能重叠,包含,交叉.
		 */
		if (mfsp.getPolicy().equals(
				MerchantFeeSettlementPolicy.POLICY_FIXEDRATE)) {
			mfspsInclude = merchantFeeSettlementPolicyDaoImpl
					.getMFSPByMrchNoAndDateInclude(mfsp.getMerchantNo(), mfsp
							.getPolicyStartDate(), mfsp.getPolicyEndDate(),
							mfsp.getPolicy(), null, null);
			if (mfspsInclude != null && mfspsInclude.size() > 0) {
				errException("此时间段内商户" + mrchName + "[" + mfsp.getMerchantNo()
						+ "]存在时间交叉或包含的固定比率策略!");
			}
			mfspsOverlapping = merchantFeeSettlementPolicyDaoImpl
					.getMFSPByMrchNoAndDateOverlapping(mfsp.getMerchantNo(),
							mfsp.getPolicyStartDate(), mfsp.getPolicyEndDate(),
							mfsp.getPolicy(), null, null);
			if (mfspsOverlapping != null && mfspsOverlapping.size() > 0) {
				errException("此时间段内商户" + mrchName + "[" + mfsp.getMerchantNo()
						+ "]存在时间重叠的固定比率策略!");
			}
		}
		/**
		 * 1-差额无追溯 和2-阶梯追溯(基本策略): 同一商户同一时间段内可以存在多个1或2,但是时间允许交叉,而且累计消费阀值不能相同.
		 */
		else if (mfsp.getPolicy().equals(
				MerchantFeeSettlementPolicy.POLICY_NORETROSPECTIVE)
				|| mfsp.getPolicy().equals(
						MerchantFeeSettlementPolicy.POLICY_LADDERRETROSPECTIVE)) {
			mfspsInclude = merchantFeeSettlementPolicyDaoImpl
					.getMFSPByMrchNoAndDateInclude(mfsp.getMerchantNo(), mfsp
							.getPolicyStartDate(), mfsp.getPolicyEndDate(),
							mfsp.getPolicy(), null, null);
			if (mfspsInclude != null && mfspsInclude.size() > 0) {
				errException("此时间段内商户" + mrchName + "[" + mfsp.getMerchantNo()
						+ "]存在该追溯策略,并时间交叉或包含!");
			}
			mfspsOverlapping = merchantFeeSettlementPolicyDaoImpl
					.getMFSPByMrchNoAndDateOverlapping(mfsp.getMerchantNo(),
							mfsp.getPolicyStartDate(), mfsp.getPolicyEndDate(),
							mfsp.getPolicy(), null, mfsp.getLimitAmount());
			if (mfspsOverlapping != null && mfspsOverlapping.size() > 0) {
				errException("此相同起始时间段内商户" + mrchName + "["
						+ mfsp.getMerchantNo() + "]存在该追溯策略,并累计消费阀值相同!");
			}
		}
		/**
		 * 3-按业务类型(基本策略): 同一商户同一时间段内有且只有一条业务类型的策略,而且时间不能重叠,包含,交叉.
		 */
		else if (mfsp.getPolicy().equals(
				MerchantFeeSettlementPolicy.POLICY_BYBUSINESSTYPE)) {
			if (mfsp.getBusinessType() == null) {
				errException("业务类型为空!");
			}
			mfspsInclude = merchantFeeSettlementPolicyDaoImpl
					.getMFSPByMrchNoAndDateInclude(mfsp.getMerchantNo(), mfsp
							.getPolicyStartDate(), mfsp.getPolicyEndDate(),
							mfsp.getPolicy(), mfsp.getBusinessType(), null);
			if (mfspsInclude != null && mfspsInclude.size() > 0) {
				errException("此时间段内商户" + mrchName + "[" + mfsp.getMerchantNo()
						+ "]存在该业务类型策略,并时间交叉或包含!");
			}
			mfspsOverlapping = merchantFeeSettlementPolicyDaoImpl
					.getMFSPByMrchNoAndDateOverlapping(mfsp.getMerchantNo(),
							mfsp.getPolicyStartDate(), mfsp.getPolicyEndDate(),
							mfsp.getPolicy(), mfsp.getBusinessType(), null);
			if (mfspsOverlapping != null && mfspsOverlapping.size() > 0) {
				errException("此时间段内商户" + mrchName + "[" + mfsp.getMerchantNo()
						+ "]存在该业务类型策略,并时间重叠!");
			}
		}
	}
}
